package com.springcloud.common.core.util;

import com.springcloud.common.core.exception.ApiException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;

/**
 * 时间工具类
 *
 * @author mori
 */
public class DateUtil {

    private static final String MINUS = "-";

    private static final String PLUS = "+";

    public static final String DEFAULT_OFFSET = "+0";

    public static final int MONTH_MAX = 9;

    /**
     * DateTimeFormatter
     */
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * DateTimeFormatter
     */
    private static final DateTimeFormatter FORMATTER_DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * DateTimeFormatter
     */
    private static final DateTimeFormatter FORMATTER_DATE_SIMPLE = DateTimeFormatter.ofPattern("yyyyMM");

    /**
     * DateTimeFormatter
     */
    public static final DateTimeFormatter FORMATTER_DATE_TIME = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");


    /**
     * 字符串转LocalDateTime
     *
     * @param text
     * @return
     */
    public static LocalDateTime textToLocalDateTime(String text) {
        return LocalDateTime.parse(text, FORMATTER);
    }

    /**
     * LocalDateTime转字符串
     *
     * @param localDateTime
     * @return
     */
    public static String localDateTimeToText(LocalDateTime localDateTime) {
        return FORMATTER.format(localDateTime);
    }

    /**
     * LocalDateTime转yyyy-MM-dd字符串
     *
     * @param localDateTime
     * @return
     */
    public static String localDateTimeToDateText(LocalDateTime localDateTime) {
        return FORMATTER_DATE.format(localDateTime);
    }

    /**
     * LocalDateTime转yyyyMM字符串
     *
     * @param localDateTime
     * @return
     */
    public static String localDateTimeToSimpleDateText(LocalDateTime localDateTime) {
        return FORMATTER_DATE_SIMPLE.format(localDateTime);
    }


    /**
     * LocalDateTime转毫秒
     *
     * @param localDateTime
     * @return
     */
    public static long localDateTimeToLong(LocalDateTime localDateTime) {
        return localDateTime.toInstant(OffsetDateTime.now().getOffset()).toEpochMilli();
    }

    /**
     * 毫秒转LocalDateTime
     *
     * @param time
     * @return
     */
    public static LocalDateTime longToLocalDateTime(long time) {
        Instant instant = Instant.ofEpochMilli(time);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    /**
     * 判断ZoneOffset是否正确
     *
     * @param offset
     * @return true 表示正确，false表示错误
     */
    public static boolean validateZoneOffset(String offset) {
        try {
            String firstChar = offset.substring(0, 1);
            if (PLUS.equals(firstChar) || MINUS.equals(firstChar)) {
                ZoneOffset.of(offset);
                return true;
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @param localDateTime
     * @param utcOffset
     * @return
     */
    public static LocalDateTime utcOffsetToLocalDateTime(LocalDateTime localDateTime, String utcOffset) {
        long time = localDateTime.toInstant(ZoneOffset.of(utcOffset)).toEpochMilli();
        return DateUtil.longToLocalDateTime(time);
    }

    public static LocalDateTime reverseUtcOffsetToLocalDateTime(LocalDateTime localDateTime, String utcOffset) {
        String firstChar = utcOffset.substring(0, 1);
        if (PLUS.equals(firstChar)) {
            utcOffset = utcOffset.replace(PLUS, MINUS);
        } else if (MINUS.equals(firstChar)) {
            utcOffset = utcOffset.replace(MINUS, PLUS);
        } else {
            throw new ApiException("Incorrect time zone format.");
        }
        long time = localDateTime.toInstant(ZoneOffset.of(utcOffset)).toEpochMilli();
        return DateUtil.longToLocalDateTime(time);
    }

    public static LocalDateTime dateToLocalDateTime(Date date){
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    /**
     * 计算两个日期相差天数
     * @param start         开始
     * @param end           结束
     * @return end - start
     */
    public static int minusDays(LocalDateTime start, LocalDateTime end) {
        long days = end.toLocalDate().toEpochDay() - start.toLocalDate().toEpochDay();
        return Long.valueOf(days).intValue();
    }

    /**
     * 时间向上请求两个月并转换成YYYYMM格式
     */
    public static String localDateTimeUpToSimpleDateText(LocalDateTime localDateTime) {
        if (Objects.isNull(localDateTime)) {
            return "";
        }
        String year = String.valueOf(localDateTime.getYear());
        int month = localDateTime.getMonthValue() + 2;
        String monthValue = String.valueOf(localDateTime.getMonthValue() + 2);
        if (month <= MONTH_MAX) {
            monthValue = "0" + monthValue;
        }
        return year + monthValue;
    }

}
